#
# Copyright 2009 Red Hat, Inc. and/or its affiliates.
#
# Licensed to you under the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version. See the files README and
# LICENSE_GPL_v2 which accompany this distribution.
#

import unittest as ut
from copy import deepcopy

import vdsClient as vdsc
import confUtils
from enum import Enum

BLANK_UUID = '00000000-0000-0000-0000-000000000000'

def generateTemplateFromSuite(suite):
    """
    Generate a config template from a test suit.
    """
    templates = []
    for testCase in suite:
        templates.append(testCase.getConfigTemplate())

    return confUtils.mergeTemplates(templates)

def validateSuiteConfig(suite, cfg):
    """
    Validate a config against a suite. Validates that all the test cases in the suite have
    all the options they need in the configuration file.

    To be used by most ruth modules.

    :returns: a touple of ``(result, message)``.
    """
    masterTemplate = generateTemplateFromSuite(suite)
    cfg = _expandGlobalCfg(masterTemplate, cfg)
    return confUtils.validateConfigFile(masterTemplate, cfg)

def _expandGlobalCfg(template, cfg):
    """
    Distribute the options defined in 'global' to all the sections.

    :returns: a new config file with the global section distributed
              to all the sections defined in the template.
    """
    #Work on a copy
    cfg = deepcopy(cfg)

    #Do we even need to work
    if not cfg.has_section("global"):
        return cfg

    for section in template:
        if not cfg.has_section(section):
            cfg.add_section(section)
        for option in template[section]:
            if not cfg.has_option("global", option):
                continue

            globalValue = cfg.get("global", option)
            cfg.set(section, option, globalValue)

    return cfg

class BasicVDSTest(ut.TestCase):

    def _getConfig(self):
        """
        Manages the configuration wrapper of a test case
        """
        if not hasattr(self, "_confDict"):
            template = self.getConfigTemplate()
            expandedCfg = _expandGlobalCfg(template, self._cfg)
            confDict = confUtils.conf2dict(template, expandedCfg)
            setattr(self, "_confDict", confDict)
        return self._confDict

    #Dynamic because the base class get the conf directly from Ruth.
    #If it were static everyone would have the basic classes wrapper.
    cfg = property(lambda self : self._getConfig())

    @classmethod
    def getConfigTemplate(cls):
        """
        Returns a config template that announces what the
        test case expects from the config file.

        .. note::
            Should be overrided by subclasses.
        """
        return {}

    @classmethod
    def setConfig(cls, cfg):
        cls._cfg = cfg

    def setUp(self):
        pass

    def tearDown(self):
        pass

    def assertVdscTaskOK(self, client, taskId, timeout=60):
        client.waitForTask(taskId, timeout)

    def assertVdscTaskFail(self, client, taskId, timeout=60):
        self.failUnlessRaises(vdsc.TaskFailed, client.waitForTask, taskId, timeout)

    def assertVdscOK(self, resp):
        """
        Asserts that a VDSC operation was successful.

        :returns: ``resp`` for piping.
        """
        code = resp['status']['code']
        msg = resp['status']['message']
        self.assertTrue(code == 0, "Test failed ([%d]%s)" % (code, msg))

        return resp

    def assertVdscFail(self, resp):
        """
        Asserts that a VDSC command failed.

        :returns: ``resp`` for piping.
        """
        code = resp['status']['code']
        msg = resp['status']['message']
        self.assertFalse(code == 0, "Test succeeded ([%d]%s)" % (code, msg))

        return resp

